﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using UMLDesigner.Widgets;
using UMLDesigner.WorkUnits;

namespace UMLDesigner.Page
{
	public partial class UMLPage : DockContent
	{
		public UMLPage()
		{
			InitializeComponent();
			selectedWidgets = new List<UMLWidget>();
			isDraggingWidget = false;

			isSelectingWidgets = false;
			selectionRectangle = new Rectangle();

			isDrawingTempLink = false;
		}

		public void SetTemporaryLinkWidget(LinkWidget link)
		{
			tempLink = link;
		}

		private void UMLPage_Paint(object sender, PaintEventArgs e)
		{
			Graphics g = e.Graphics;
			LinearGradientBrush backgroundBrush = new LinearGradientBrush(ClientRectangle, Color.LemonChiffon, Color.White, 45.0f);

			g.FillRectangle(backgroundBrush, ClientRectangle);

			foreach (UMLWidget w in Document.Widgets)
			{
				if (selectedWidgets.Contains(w) == true)
				{
					if (focusedWidget == w)
					{
						w.DrawFocused(g);
					}
					else
					{
						w.DrawSelected(g);
					}
				}
				else
				{
					w.DrawItem(g);
				}
			}

			if (isSelectingWidgets == true &&
				selectionRectangle.Height != 0 &&
				selectionRectangle.Width != 0)
			{
				Option option = CurrentOption.Instance.Option;
				Color tl = option.SelectionRectangleTopLeftColor; // tl == top left
				Color br = option.SelectionRectangleBottomRightColor; // br == bottom right
				LinearGradientBrush b = new LinearGradientBrush(selectionRectangle, tl, br, 45.0f);
				g.FillRectangle(b, selectionRectangle);
				g.DrawRectangle(new Pen(tl), selectionRectangle);
			}

			if (isDrawingTempLink == true)
			{
				tempLink.DrawItem(g);
			}
		}

		public Document Document
		{
			get;
			set;
		}

		private void ClearSelectionIfShiftUp()
		{
			bool isShiftDown = (Control.ModifierKeys & Keys.Shift) == Keys.Shift;

			if (isShiftDown == false)
			{
				selectedWidgets.Clear();
			}
		}

		private UMLWidget FindWidget(Point pt)
		{
			UMLWidget clickedWidget = null;

			foreach (UMLWidget w in Document.Widgets)
			{
				if (w.IsIn(pt))
				{
					clickedWidget = w;
				}
			}

			return clickedWidget;
		}

		private void UMLPage_MouseDown(object sender, MouseEventArgs e)
		{
			UMLWidget clickedWidget = FindWidget(new Point(e.X, e.Y));

			if (e.Button == System.Windows.Forms.MouseButtons.Left)
			{
				lastPoint = new Point(e.X, e.Y);
				dragStartPoint = lastPoint;

				// Handle selected widget list
				if (clickedWidget != null)
				{
					focusedWidget = clickedWidget;

					if (selectedWidgets.Contains(clickedWidget) == false)
					{
						ClearSelectionIfShiftUp();
						selectedWidgets.Add(clickedWidget);
					}

					isDraggingWidget = true;
					moveWidgetsWorkUnit = new MoveWidgetsWorkUnit(selectedWidgets, lastPoint);

					if (tempLink != null)
					{
						if (tempLink.IsThisSourceWidgetOK(clickedWidget) == false)
						{
							tempLink = null;
						}
						else
						{
							tempLink.SourceWidget = clickedWidget;
							tempLink.SourceSlot.Location = 
								tempLink.DestinationSlot.Location = new Point(clickedWidget.Location.X + clickedWidget.Size.Width / 2,
								clickedWidget.Location.Y + clickedWidget.Size.Height / 2);
							isDrawingTempLink = true;
						}
					}
				}
				else  // Handle selection area
				{
					ClearSelectionIfShiftUp();

					isSelectingWidgets = true;
				}
			}       
		}

		private void UMLPage_MouseMove(object sender, MouseEventArgs e)
		{
			if (isDrawingTempLink == true)
			{
				tempLink.DestinationSlot.Location = new Point(e.X, e.Y);

				UMLWidget w = FindWidget(new Point(e.X, e.Y));

				Invalidate();
			}
			else
			{
				if (isDraggingWidget)
				{
					int dx = e.X - lastPoint.X;
					int dy = e.Y - lastPoint.Y;

					foreach (UMLWidget w in selectedWidgets)
					{
						int nx = w.Location.X + dx;
						int ny = w.Location.Y + dy;
						w.Location = new Point(nx, ny);
					}
					lastPoint = new Point(e.X, e.Y);
					Invalidate();
				}
				else if (isSelectingWidgets)
				{
					Point tl = new Point(Math.Min(e.X, lastPoint.X), Math.Min(e.Y, lastPoint.Y)); //tl == top left
					Point br = new Point(Math.Max(e.X, lastPoint.X), Math.Max(e.Y, lastPoint.Y)); //br == bottom right

					selectionRectangle.Location = tl;
					selectionRectangle.Size = new Size(br.X - tl.X, br.Y - tl.Y);

					//ClearSelectionIfShiftUp();

					foreach (UMLWidget w in Document.Widgets)
					{
						if (w.IsIn(selectionRectangle) == true &&
							selectedWidgets.Contains(w) == false)
						{
							selectedWidgets.Add(w);
						}
					}
					Invalidate();
				}
			}
		}

		private void UMLPage_MouseUp(object sender, MouseEventArgs e)
		{
			if (isDrawingTempLink == true)
			{
				UMLWidget w = FindWidget(new Point(e.X, e.Y));
				if (tempLink.IsThisDestinationWidgetOK(w) == true)
				{
					tempLink.DestinationWidget = w;
					tempLink.GetSlotsFromWigets();
					Document.History.Add(new NewLinkWidgetWorkUnit(tempLink));
					Document.IsModified = true;
					tempLink = null;
				}
			}
			else
			{
				if (isDraggingWidget == true)
				{
					if (e.X != dragStartPoint.X || e.Y != dragStartPoint.Y)
					{
						moveWidgetsWorkUnit.NewPosition = new Point(e.X, e.Y);
						Document.History.Add(moveWidgetsWorkUnit);
						Document.IsModified = true;
						moveWidgetsWorkUnit = null;
					}
				}
			}
			isDraggingWidget = false;
			isSelectingWidgets = false;
			isDrawingTempLink = false;
			Cursor = Cursors.Arrow;
			Invalidate();
		}

		private void UMLPage_Load(object sender, EventArgs e)
		{
		}

		private UMLWidget focusedWidget;
		private List<UMLWidget> selectedWidgets;
		private bool isDraggingWidget;
		private Point lastPoint;
		private Point dragStartPoint;
		private MoveWidgetsWorkUnit moveWidgetsWorkUnit;

		private Rectangle selectionRectangle;
		private bool isSelectingWidgets;

		private LinkWidget tempLink;
		private bool isDrawingTempLink;
	}
}
